//
//  ViewController.swift
//  STest
//
//  Created by wang tiao on 2025/9/1.
//

import UIKit
import WalletCore
import WalletCoreSwiftProtobuf
import BigInt
import Foundation

enum Blockchain {
    case bsc
    case tron
}

struct TransactionInfo {
    let success: Bool
    let blockNumber: Int?
    let from: String?
    let to: String?
    let value: String?
    let rawData: [String: Any]?
}

func queryTransaction(chain: Blockchain, txHash: String, completion: @escaping (TransactionInfo?) -> Void) {
    let urlString: String
    let payload: [String: Any]
    
    switch chain {
    case .bsc:
        urlString = "https://data-seed-prebsc-1-s1.binance.org:8545" // BSC 测试网
        payload = [
            "jsonrpc": "2.0",
            "method": "eth_getTransactionByHash",
            "params": [txHash],
            "id": 1
        ]
    case .tron:
        urlString = "https://api.shasta.trongrid.io/jsonrpc" // Tron Shasta 测试网
        payload = [
            "jsonrpc": "2.0",
            "method": "gettransactionbyid",
            "params": [txHash],
            "id": 1
        ]
    }
    
    guard let url = URL(string: urlString),
          let body = try? JSONSerialization.data(withJSONObject: payload) else {
        completion(nil)
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = body
    
    URLSession.shared.dataTask(with: request) { data, _, error in
        guard error == nil, let data = data else {
            completion(nil)
            return
        }
        
        guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
            completion(nil)
            return
        }
        
        switch chain {
        case .bsc:
            if let result = json["result"] as? [String: Any] {
                let info = TransactionInfo(
                    success: true,
                    blockNumber: Int(result["blockNumber"] as? String ?? "", radix: 16),
                    from: result["from"] as? String,
                    to: result["to"] as? String,
                    value: result["value"] as? String,
                    rawData: result
                )
                completion(info)
            } else {
                completion(nil)
            }
        case .tron:
            if let result = json["result"] as? [String: Any] {
                let rawData = result["raw_data"] as? [String: Any]
                let info = TransactionInfo(
                    success: true,
                    blockNumber: rawData?["ref_block_num"] as? Int,
                    from: rawData?["contract"] as? String,
                    to: rawData?["contract"] as? String,
                    value: nil,
                    rawData: rawData
                )
                completion(info)
            } else {
                completion(nil)
            }
        }
    }.resume()
}


func fetchTronTransaction(txid: String, completion: @escaping ([String: Any]?) -> Void) {
    let url = URL(string: "https://api.shasta.trongrid.io/walletsolidity/gettransactionbyid")!
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let body: [String: Any] = ["value": txid]
    request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard error == nil, let data = data else {
            print("网络请求失败:", error?.localizedDescription ?? "")
            completion(nil)
            return
        }
        
        if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
            completion(json)
        } else {
            print("解析JSON失败")
            completion(nil)
        }
    }.resume()
}

extension String {
    /// 将 TRX 金额 (单位: TRX) 转换为 Sun (最小单位)
    var trxToSun: BigUInt? {
        guard let decimalAmount = Decimal(string: self) else { return nil }
        let multiplier = NSDecimalNumber(decimal: pow(10, 6)) // 1 TRX = 1_000_000 Sun
        let sunDecimal = decimalAmount * multiplier.decimalValue
        return BigUInt(truncating: NSDecimalNumber(decimal: sunDecimal) as Decimal)
    }
    
    /// 将 BNB 金额 (单位: BNB) 转换为 Wei (最小单位)
     var bnbToWei: BigUInt? {
         guard let decimalAmount = Decimal(string: self) else { return nil }
         let multiplier = NSDecimalNumber(decimal: pow(10, 18))
         let weiDecimal = decimalAmount * multiplier.decimalValue
         return BigUInt(truncating: NSDecimalNumber(decimal: weiDecimal) as Decimal)
     }
    
}

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
    
        
//        signTronTransaction()
        //
        //        createBSCWallet()
        //        createTronWallet()
        //
                // ✅ 使用示例
                fetchBSCBalance(address: "0xFc26939fC4BfceCB71AAa56c95919a3Ee456da55") { balance in
                    print("BSC余额: \(balance ?? 0) BNB")
                }
        //
//                fetchTronBalance(address: "TJhJQLbLsyQiVPzDBSTnb1e8CGHhX9227n") { balance in
//                    print("TRX余额：\(balance ?? 0)")
//                }
//
        printf("开始请求")
        
        queryTransaction(chain: .bsc, txHash: "0xdf971bd13ef5ac626d1e2f348ef4bcf453ede32eb0986f303d25cf791887ff6d") { info in
            print("BSC交易详情:", info ?? "未找到")
        }

        fetchTronTransaction(txid: "0346d7d6b25812a21a0931e0afd7666796892475b3239a2ef936da1a3d6d2b9b") { info in
            print("Tron交易详情:", info ?? "未找到")
        }
        
        return;
        
        var responseNonce: UInt64?
        var responseGasPrice: UInt64?
        var responseGasLimit: UInt64?

        let queue = DispatchQueue(label: "taskQueue", attributes: .concurrent)
        let group = DispatchGroup()
        group.enter()
        queue.async {
            self.fetchNonce(address: "0xFc26939fC4BfceCB71AAa56c95919a3Ee456da55") { nonce in
                print("nonce=\(nonce)")
                responseNonce = nonce
                group.leave()
            }
        }
        
        
        group.enter()
        queue.async {
            self.fetchGasPrice { gasPrice in
                print("gasPrice=\(gasPrice)")
                responseGasPrice = gasPrice
                group.leave()
            }
        }

        group.enter()
        queue.async {
            
            let fromAddress = "0xFc26939fC4BfceCB71AAa56c95919a3Ee456da55"
            let toAddress = "0x7674BaF3C26c75b3EeDB3a0691249Ebbc16a6f16"
            
            printf("UInt64(0.01 * 1e18)=\(UInt64(0.01 * 1e18))")

            // 示例：估算 0.01 BNB 转账所需 gasLimit
            let valueInWei = String(format: "0x%llx", UInt64(0.01 * 1e18)) // 转换成十六进制 wei

            self.fetchBSCGasLimit(from: fromAddress, to: toAddress, valueInWei: valueInWei) { gasLimit in
                if let gasLimit = gasLimit {
                    print("估算的 gasLimit:", gasLimit)
                } else {
                    print("获取 gasLimit 失败")
                }
                responseGasLimit = gasLimit
                group.leave()
            }
    
        }

        // 所有任务完成后的通知
        group.notify(queue: DispatchQueue.main) {
            printf("所有任务执行完毕")
            
            guard let nonce = responseNonce,
                  let gasPrice = responseGasPrice,
                  let gasLimit = responseGasLimit else {
                return
            }
            
            printf("nonce=\(nonce)")
            printf("gasPrice=\(gasPrice)")
            printf("gasLimit=\(gasLimit)")
            
            self.signBSCTransaction(amount: BigUInt(0.001 * 1e18), gasPrice: BigUInt(gasPrice), gasLimit: BigUInt(gasLimit), nonce: BigUInt(nonce))
            
  
            
        }
     

    }
    
    
    /// 获取 BSC 测试网 gasLimit（自动估算）
    func fetchBSCGasLimit(
        from: String,
        to: String,
        valueInWei: String = "0x0",  // 转账金额（单位：wei）
        data: String? = nil,         // 合约调用数据，可选
        completion: @escaping (UInt64?) -> Void
    ) {
        // BSC Testnet RPC
        let rpcURL = URL(string: "https://bsc-testnet-rpc.publicnode.com")!
        var request = URLRequest(url: rpcURL)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        // 构造 RPC 参数
        var txParams: [String: Any] = [
            "from": from,
            "to": to,
            "value": valueInWei
        ]
        if let data = data {
            txParams["data"] = data
        }

        let payload: [String: Any] = [
            "jsonrpc": "2.0",
            "id": 1,
            "method": "eth_estimateGas",
            "params": [txParams]
        ]

        request.httpBody = try? JSONSerialization.data(withJSONObject: payload)

        // 发送请求
        URLSession.shared.dataTask(with: request) { data, _, error in
            guard
                error == nil,
                let data = data,
                let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                let resultHex = json["result"] as? String
            else {
                completion(nil)
                return
            }

            // 转换为十进制 gasLimit
            let gasLimit = UInt64(resultHex.replacingOccurrences(of: "0x", with: ""), radix: 16)
            printf("json=\(json)", "gasLimit=\(gasLimit)")
            completion(gasLimit)
        }.resume()
    }
    
    func fetchGasPrice(completion: @escaping (UInt64?) -> Void) {
        
        let bscTestnetRPC = "https://data-seed-prebsc-1-s1.binance.org:8545"
        
        let rpcURL = URL(string: bscTestnetRPC)!
        let params: [String: Any] = [
            "jsonrpc": "2.0",
            "method": "eth_gasPrice",
            "params": [],
            "id": 1
        ]
        
        var request = URLRequest(url: rpcURL)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try! JSONSerialization.data(withJSONObject: params)
        
        URLSession.shared.dataTask(with: request) { data, _, _ in
            guard let data = data else { completion(nil); return }
            guard
                let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                let resultHex = json["result"] as? String
            else {
                completion(nil)
                return
            }
            
            printf("json=\(json)")
            
            let gasPrice = UInt64(resultHex.dropFirst(2), radix: 16)
            printf("gasPrice=\(gasPrice)")
            completion(gasPrice)
        }.resume()
    }
    
    func fetchNonce(address: String, completion: @escaping (UInt64?) -> Void) {
        let params: [String: Any] = [
            "jsonrpc": "2.0",
            "method": "eth_getTransactionCount",
            "params": [address, "latest"],
            "id": 1
        ]
        
        let rpcURL = URL(string: "https://data-seed-prebsc-1-s1.binance.org:8545")!
        var request = URLRequest(url: rpcURL)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try! JSONSerialization.data(withJSONObject: params)

        URLSession.shared.dataTask(with: request) { data, _, _ in
            guard
                let data = data,
                let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                let resultHex = json["result"] as? String,
                let nonce = UInt64(resultHex.dropFirst(2), radix: 16)
            else {
                completion(nil)
                return
            }
            
            printf("json=\(json)", nonce)
            
            completion(nonce)
        }.resume()
    }
    
    func createBSCWallet() {
        // 1. 创建助记词
        guard let wallet = HDWallet(strength: 128, passphrase: "") else {
            return
        }
        let mnemonic = wallet.mnemonic
        
        // 2. 使用 CoinType.smartChain
        let coin = CoinType.smartChain
        let privateKey = wallet.getKeyForCoin(coin: coin)
        let address = coin.deriveAddress(privateKey: privateKey)
        
        print("=== BSC 钱包 ===")
        print("助记词: \(mnemonic)")
        print("私钥: \(privateKey.data.hexString)")
        print("地址: \(address)") // 形如 0x 开头
        
        print("BSC 地址有效:", CoinType.smartChain.validate(address: address))
        
    }
    
    
    func createTronWallet() {
        guard let wallet = HDWallet(strength: 128, passphrase: "") else {
            return
        }
        let mnemonic = wallet.mnemonic
        
        let coin = CoinType.tron
        let privateKey = wallet.getKeyForCoin(coin: .tron)
        let address = coin.deriveAddress(privateKey: privateKey)
        
        print("=== TRON 钱包 ===")
        print("助记词: \(mnemonic)")
        print("私钥: \(privateKey.data.hexString)")
        print("地址: \(address)") // T 开头
        
        print("TRON 地址有效:", CoinType.tron.validate(address: address))
    }
    
    func fetchBSCBalance(address: String, completion: @escaping (Double?) -> Void) {
        
        let rpcURL = URL(string: "https://data-seed-prebsc-1-s1.binance.org:8545")!

//        let rpcURL = URL(string: "https://bsc-dataseed.binance.org")!
        
        // JSON-RPC 请求体
        let body: [String: Any] = [
            "jsonrpc": "2.0",
            "id": 1,
            "method": "eth_getBalance",
            "params": [address, "latest"]
        ]
        
        var request = URLRequest(url: rpcURL)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: body)
        
        URLSession.shared.dataTask(with: request) { data, _, _ in
            guard
                let data = data,
                let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                let resultHex = json["result"] as? String
            else {
                completion(nil)
                return
            }
            
            print("json=\(json)")
            
            // 余额为十六进制 wei 单位
            let balanceWei = UInt64(resultHex.dropFirst(2), radix: 16) ?? 0
            let balanceBNB = Double(balanceWei) / pow(10, 18)
            completion(balanceBNB)
        }.resume()
    }
    
    func fetchTronBalance(address: String, completion: @escaping (Double?) -> Void) {
        let url = URL(string: "https://api.shasta.trongrid.io/v1/accounts/\(address)")!
        
        URLSession.shared.dataTask(with: url) { data, _, error in
            guard error == nil, let data = data else {
                completion(nil)
                return
            }
            do {
                if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
                    
                    print("json=\(json)")
                    
                    if let dataArray = json["data"] as? [[String: Any]],
                       let account = dataArray.first,
                       let balance = account["balance"] as? Double {
                        
                        // TRX = balance / 1_000_000 (Sun -> TRX)
                        completion(balance / 1_000_000.0)
                    } else {
                        completion(0.0)
                    }
                } else {
                    // 没有 data 说明账户还未激活或者余额为 0
                    completion(0.0)
                }
            } catch {
                completion(nil)
            }
        }.resume()
    }
    
    func signBSCTransaction(amount: BigUInt, gasPrice: BigUInt, gasLimit: BigUInt, nonce: BigUInt) {
        // 私钥
        let privateKeyHex = "17df23150ab406cb15e61791e3b06777bb0832de671df82b4b5fe7322e2dc0db"
        let privateKey = PrivateKey(data: Data(hexString: privateKeyHex)!)!
        
        // 发送方地址
        let fromAddress = CoinType.smartChain.deriveAddress(privateKey: privateKey)
        print("From:", fromAddress)
        
        // 接收方地址
        let toAddress = "0x7674BaF3C26c75b3EeDB3a0691249Ebbc16a6f16"
        
        let input = EthereumSigningInput.with {
            
            $0.chainID = Data(hexString: "0x61")! // BSC 测试网 = 97 = 0x61
//            $0.chainID = Data(hexString: "0x38")! // BSC 主网 = 56 (0x38)
            $0.nonce = nonce.serialize()
            $0.gasPrice = gasPrice.serialize()
            $0.gasLimit = gasLimit.serialize()
            $0.toAddress = toAddress
            $0.transaction = EthereumTransaction.with { transaction in
                transaction.transfer = EthereumTransaction.Transfer.with {
                    $0.amount = amount.serialize()
                }
            }
            $0.privateKey = privateKey.data
        }
        
        let output: EthereumSigningOutput = AnySigner.sign(input: input, coin: .smartChain)
        print("签名后的原始交易：\(output.encoded.hexString)")
        
        let signedRawTx = "0x" + output.encoded.hexString

        broadcastBSCTransaction(rawTransaction: signedRawTx) { success, txidOrError in
            if success {
                print("交易广播成功，txid: \(txidOrError ?? "")")
            } else {
                print("交易广播失败: \(txidOrError ?? "")")
            }
        }
        
    }
    
    func signTronTransaction() {
        let privateKeyHex = "42f3016b4dd6d40349e189b9ae06ee4d52b07eb34bdc338a27bce1d3e49e98b8"
        let privateKey = PrivateKey(data: Data(hexString: privateKeyHex)!)!
        signAndBroadcastTronTransaction(privateKeyHex: privateKeyHex, toAddress: "THnftGvPuoLd1RqMmaHF5vRYHmb4zkPC43", amountSun: 2_000_000)
    }
    
    func broadcastTronTransaction(signedJSON: String, completion: @escaping (Bool, String?) -> Void) {
        let url = URL(string: "https://api.shasta.trongrid.io/wallet/broadcasttransaction")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = signedJSON.data(using: .utf8)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            guard error == nil, let data = data else {
                completion(false, error?.localizedDescription)
                return
            }
            
            if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
                if let result = json["result"] as? Bool, result == true {
                    completion(true, json["txid"] as? String)
                } else {
                    completion(false, "\(json)")
                }
            } else {
                completion(false, "无法解析响应")
            }
        }.resume()
    }
    
    func signAndBroadcastTronTransaction(privateKeyHex: String, toAddress: String, amountSun: Int64) {

        let privateKey = PrivateKey(data: Data(hexString: privateKeyHex)!)!
        
        let url = URL(string: "https://api.shasta.trongrid.io/wallet/getnowblock")!
        URLSession.shared.dataTask(with: url) { data, _, _ in
            guard
                let data = data,
                let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                let blockHeader = (json["block_header"] as? [String: Any]),
                let rowData = blockHeader["raw_data"] as? [String: Any],
                let blockNumber = rowData["number"] as? Int64,
                let parentHashHex = rowData["parentHash"] as? String,
                let txTrieRoot = rowData["txTrieRoot"] as? String,
                let witness_address = rowData["witness_address"] as? String,
                let timestamp = rowData["timestamp"] as? Int64,
                let version = rowData["version"] as? Int32
            else {
                print("获取最新区块失败")
                return
            }
            
            printf("json=\(json)")
            
            guard let parentHashData = Data(hexString: parentHashHex),
                  let witnessAddressData = Data(hexString: witness_address),
                  let txTrieRootData = Data(hexString: txTrieRoot)  else {
                return
            }
            
            let input = TronSigningInput.with {
                $0.transaction = TronTransaction.with {
                    $0.blockHeader = TW_Tron_Proto_BlockHeader.with {
                        $0.number = Int64(blockNumber)
                        $0.parentHash = parentHashData
                        $0.timestamp = timestamp
                        $0.txTrieRoot = txTrieRootData
                        $0.witnessAddress = witnessAddressData
                        $0.version = version
                    }
                    
                    $0.transfer = TronTransferContract.with {
                        $0.ownerAddress = CoinType.tron.deriveAddress(privateKey: privateKey)
                        $0.toAddress = toAddress
                        $0.amount = amountSun
                    }
                }
                $0.privateKey = privateKey.data
            }
            
            let output: TronSigningOutput = AnySigner.sign(input: input, coin: .tron)
            print("签名交易 JSON:")
            print(output.json)
            
            if let txJSON = output.json.data(using: .utf8) {
                var request = URLRequest(url: URL(string: "https://api.shasta.trongrid.io/wallet/broadcasttransaction")!)
                request.httpMethod = "POST"
                request.setValue("application/json", forHTTPHeaderField: "Content-Type")
                request.httpBody = txJSON
                
                URLSession.shared.dataTask(with: request) { data, _, _ in
                    if let data = data, let resp = String(data: data, encoding: .utf8) {
                        print("广播结果: \(resp)")
                    }
                }.resume()
            }
            
        }.resume()
    }
    
    

    /// 广播 BSC 交易
    /// - Parameters:
    ///   - rawTransaction: 已签名的原始交易 hex 字符串，例如 output.encoded.hexString
    ///   - rpcURL: BSC 测试网或主网 RPC 地址
    ///   - completion: 返回是否成功和 txid / 错误信息
    func broadcastBSCTransaction(rawTransaction: String,
                                 rpcURL: String = "https://data-seed-prebsc-1-s1.binance.org:8545",
                                 completion: @escaping (Bool, String?) -> Void) {
        
        let url = URL(string: rpcURL)!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        // 构造 JSON-RPC 请求体
        let params: [String: Any] = [
            "jsonrpc": "2.0",
            "method": "eth_sendRawTransaction",
            "params": [rawTransaction],
            "id": 1
        ]
        
        guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else {
            completion(false, "构造请求失败")
            return
        }
        
        request.httpBody = httpBody
        
        URLSession.shared.dataTask(with: request) { data, _, error in
            if let error = error {
                completion(false, error.localizedDescription)
                return
            }
            
            guard let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                completion(false, "无法解析 RPC 响应")
                return
            }
            
            // eth_sendRawTransaction 返回 txid
            if let txid = json["result"] as? String {
                completion(true, txid)
            } else if let error = json["error"] as? [String: Any],
                      let message = error["message"] as? String {
                completion(false, message)
            } else {
                completion(false, "未知错误")
            }
        }.resume()
    }
 
}


//"f86b808405f5e100825208947674baf3c26c75b3eedb3a0691249ebbc16a6f1687038d7ea4c68000808193a0b8427de50afa8eeae18f0388d0fb8940dda7dccde06f6fb4fc801a8803f1fcfea01f5f880c4797cfb3477845734e9f237d15cc1a158502348571479b3a27f4b36d"

//"0xdf971bd13ef5ac626d1e2f348ef4bcf453ede32eb0986f303d25cf791887ff6d"
